/*  Beamed (the only limit is your imagination) */
/*  Copyright (C) 2012  Michael F�rst */
/*  */
/*  This program is free software; you can redistribute it and/or modify it */
/*  under the terms of the GNU General Public License as published by the */
/*  Free Software Foundation; either version 3 of the License, or (at your */
/*  option) any later version. */
/*  */
/*  This program is distributed in the hope that it will be useful, but */
/*  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY */
/*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License */
/*  for more details. */
/*  */
/*  You should have received a copy of the GNU General Public License along */
/*  with this program; if not, see <http://www.gnu.org/licenses/>. */

function HCP_CRenderEngine() {
	var that = this;
	var canvas = null;
	var ctx = null;
	var width = 0;
	var height = 0;
	var default_width = 0;
	var default_height = 0;
	var screen_radius = 0;
	var camera = {
		x : 0,
		y : 0,
		zoom : 1,
		angle : 0
	};
	var LiveRenderQueue = new Array();
	var BufferedObjects = new Array();
	var Buffer = new Array();
	var current_buffer = null;
	var fullscreen = false;
	var start_time = new Date().getTime();

	
	/* no need to implement this function due to Text obj has buffer itself */
	function updateBuffer(step) {
	}
	
	/* no need to implement this function due to Text obj has buffer itself */
	function renderBuffer() {
	}

	function renderLiveObjects(step) {
		var partial = data_width / width;
		if (partial < data_height / height) {
			partial = data_height / height;
		}
		for (var i = 0; i < LiveRenderQueue.length; i++) {
			LiveRenderQueue[i].draw(ctx, step, camera.zoom/partial, camera.x, camera.y, screen_radius);
		}
	}

	/*
	 * gives you back the time the presentation is currently running, resets on
	 * reload
	 */
	function getPresentationTime() {
		var time = (((new Date().getTime()) - start_time) / 1000);
		var time_str = "";
		var time_h = Math.floor((time / 3600));
		time = time - (time_h * 3600);
		var time_m = Math.floor((time / 60));
		time = time - (time_m * 60);
		if (time_h < 10) {
			time_str = "0" + time_h;
		} else {
			time_str += "" + time_h;
		}
		if (time_m < 10) {
			time_str += ":0" + time_m;
		} else {
			time_str += ":" + time_m;
		}
		if (Math.floor(time) < 10) {
			time_str += ":0" + Math.floor(time);
		} else {
			time_str += ":" + Math.floor(time);
		}
		return time_str;
	}

	/* switch fullscreen flag & change pos attr for correct positioning */
	this.toggleFullscreen = function() {
		if (fullscreen) {
			canvas.style.position = "relative";
			fullscreen = false;
		} else {
			canvas.style.position = "absolute";
			fullscreen = true;
		}
		that.resize();
	};
	/* force a certain fullscreen state */
	this.forceFullscreen = function(b_full) {
		if (b_full == true) {
			canvas.style.position = "absolute";
			fullscreen = true;
		} else {
			canvas.style.position = "relative";
			fullscreen = false;
		}
		resize();
	};

	this.getPartial = function() {
		var partial = data_width / width;
		if (partial < data_height / height) {
			partial = data_height / height;
		}
		return partial;
	};
	
	var reset_observer = 0;

	this.render = function(step, fps) {
		// This reset observer, avoids drifting away presentation (due to floating comma errors)
		if (reset_observer > 60) {
			that.resize();
			reset_observer = 0;
		}
		reset_observer += 1;
		/* the bufferable objects */
		ctx.fillStyle = "rgb(0, 0, 0)";
		updateBuffer(step);
		/* clean canvas */
		ctx.clearRect(0, 0, width, height);
		/* generate canvas background */
		if (Presentation.bkgGrad == null) {
			Presentation.bkgGrad = ctx.createLinearGradient(0, 0, 0, height);
			Presentation.bkgGrad.addColorStop(0, '#E0E0E0');
			Presentation.bkgGrad.addColorStop(0.1, '#EEEEEE');
			Presentation.bkgGrad.addColorStop(0.2, '#F0F0F0');
			Presentation.bkgGrad.addColorStop(1, '#FFFFFF');
		}
		/* draw background */
		ctx.fillStyle = Presentation.bkgGrad;
		ctx.fillRect(0, 0, width, height);

		/* moving the canvas */
		ctx.translate(width / 2, height / 2);
		ctx.rotate(camera.angle * Math.PI / 180);
		ctx.translate(camera.x, camera.y);
		/* rendering */
		ctx.fillStyle = "rgb(0, 0, 0)";
		renderBuffer();
		renderLiveObjects(step);
		/* moving the canvas back */
		ctx.translate(-camera.x, -camera.y);
		ctx.rotate((-camera.angle) * Math.PI / 180);
		ctx.translate(-width / 2, -height / 2);

		/* create correct proportions, blackout at the right side */
		ctx.fillStyle = "rgba(0, 0, 0, 0.9)";
		if (width > data_width / that.getPartial()) {
			ctx.fillRect(0, 0, (width - data_width / that.getPartial()) / 2, height);
			ctx.fillRect(width - (width - data_width / that.getPartial()) / 2, 0,
					(width - data_width / that.getPartial()) / 2, height);
		}
		if (height > data_height / that.getPartial()) {
			ctx
					.fillRect(0, 0, width,
							(height - data_height / that.getPartial()) / 2);
			ctx.fillRect(0, height - (height - data_height / that.getPartial()) / 2,
					width, (height - data_height / that.getPartial()) / 2);
		}

		/* Bottom pane */
		if (Presentation.bottombar == true) {
			/* Inventor notice */
			ctx.font = "12px 'Helvetica'";
			ctx.fillStyle = "rgb(128,128,128)";
			ctx.textAlign = 'center';
			ctx.textBaseline = 'top';
			ctx.fillText("Invented by Michael Fuerst 2012", width / 2,
					height - 15);
			ctx.font = "12px 'Helvetica'";
			ctx.fillStyle = "rgb(128,128,128)";
			ctx.textAlign = 'center';
			ctx.textBaseline = 'top';
			ctx.font = "12px 'Helvetica'";
			ctx.fillText("Time: " + getPresentationTime(), 50, height - 15);
			ctx.font = "20px 'Helvetica'";
			var data_steps = Presentation.getStepsCount();
			if (data_steps < 10) {
				ctx.fillText("(" + step + "/" + data_steps + ")", width - 30,
						height - 22);
			} else if (data_steps < 100) {
				if (step < 10) {
					ctx.fillText("(0" + step + "/" + data_steps + ")",
							width - 40, height - 22);
				} else {
					ctx.fillText("(" + step + "/" + data_steps + ")",
							width - 40, height - 22);
				}
			} else {
				if (step < 10) {
					ctx.fillText("(00" + step + "/" + data_steps + ")",
							width - 50, height - 22);
				} else if (step < 100) {
					ctx.fillText("(0" + step + "/" + data_steps + ")",
							width - 50, height - 22);
				} else {
					ctx.fillText("(" + step + "/" + data_steps + ")",
							width - 50, height - 22);
				}
			}
		}
		if (Presentation.debug == true) {
			ctx.font = "10px 'Helvetica'";
			ctx.textAlign = 'center';
			ctx.textBaseline = 'top';
			if (fps > 60) {
				ctx.fillStyle = "rgb(0,255,255)";
			} else if (fps > 30) {
				ctx.fillStyle = "rgb(0,255,0)";
			} else if (fps > 15) {
				ctx.fillStyle = "rgb(255,255,0)";
			} else {
				ctx.fillStyle = "rgb(255,0,0)";
			}
			ctx.fillText("FPS: "+fps.toFixed(0), 30, 15);
		}

		/* empty the LiveRenderQueue, because it has been drawn */
		LiveRenderQueue = new Array();
	};
	this.getSize = function () {
		return {width:width, height:height};
	};
	
	this.getCamera = function() {
		return camera;
	};
	this.setCamera = function(cam) {
		camera = cam;
	};

	this.appendLiveRenderQueue = function(obj) {
		LiveRenderQueue[LiveRenderQueue.length] = obj;
	};
	this.appendBuffer = function(obj) {
		BufferedObjects[BufferedObjects.length] = obj;
	};
	this.clearBuffer = function() {
		BufferedObjects = new Array();
		Buffer = null;
	};

	/* give out the absolute canvas position */
	this.getCanvasPosition = function() {
		var elem = canvas, tagname = "", x = 0, y = 0;
		while ((typeof (elem) == "object")
				&& (typeof (elem.tagName) != "undefined")) {
			y += elem.offsetTop;
			x += elem.offsetLeft;
			tagname = elem.tagName.toUpperCase();
			if (tagname == "BODY")
				elem = 0;
			if (typeof (elem) == "object")
				if (typeof (elem.offsetParent) == "object")
					elem = elem.offsetParent;
		}
		position = new Object();
		position.x = x;
		position.y = y;
		return position;
	};

	this.init = function(b_fullscreen, init_width, init_height, container) {
		fullscreen = b_fullscreen;
		/* create a canvas element */
		canvas = document.createElement('canvas');
		canvas.setAttribute('id', 'unnamedpresentationcontainer');
		/* bind it to the given container or the body */
		if (container == null) {
			document.body.appendChild(canvas);
		} else {
			document.getElementById(obj).appendChild(canvas);
		}
		/* fix the style to display it correctly */
		if (fullscreen) {
			canvas.style.position = "absolute";
		} else {
			canvas.style.position = "relative";
		}
		canvas.style.top = "0";
		canvas.style.left = "0";
		canvas.style.display = 'block';
		/* extract the context, that is required for rendering */
		ctx = canvas.getContext('2d');
		ctx.save();
		default_width = init_width;
		default_height = init_height;
		that.resize();
		window.onresize = function () {
			that.resize();
		};
		/*
		 * give back the canvas to give other classes the possibility to append
		 * InputListeners to it
		 */
		return canvas;
	};

	this.resize = function() {
		if (fullscreen == true) {
			width = window.innerWidth;
			height = window.innerHeight;
		} else {
			width = default_width;
			height = default_height;
		}
		canvas.width = width;
		canvas.height = height;
		screen_radius = lengthOf(width, height) / 2;
	};
	function lengthOf(a, b) {
		return 1;
	}
}